home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 March / EnigmA AMIGA RUN 05 (1996)(G.R. Edizioni)(IT)[!][issue 1996-03][Skylink CD IV].iso / earcd / util1 / scrdl421.lha / SecureDel42_1 / SecureDelete.c < prev   
C/C++ Source or Header  |  1995-08-10  |  6KB  |  209 lines

  1. /*
  2.  * $VER: SecureDelete.c 42.1 (10.8.95)
  3.  *
  4.  * by Bruce M. Simpson <bsimpson@touchdwn.demon.co.uk>
  5.  *
  6.  * A 'secure' deletion program for files on any filesystem.  It works by
  7.  * overwriting the data of the file itself, and making sure the buffers are
  8.  * forced out to disk.  Later versions will probably incorporate a special
  9.  * algorithm designed to wipe out all traces of the file's data from the
  10.  * magnetic medium.  The old file header does NOT get deleted, as this is
  11.  * up to the filesystem, however file headers can be removed from Amiga
  12.  * filesystem volumes by using a tool such as ReOrg, which is admittedly
  13.  * overkill, but there's no 100% kosher way to eliminate the file headers
  14.  * unless the handler specifically a custom packet for doing so...
  15.  *
  16.  * I could make this remove every single trace of a file from an AmigaDOS
  17.  * volume, but hey, life's too short, and anyway I see the blocks getting
  18.  * overwrittem when I check up using DiskX and SnoopDos, so I'm satisfied.
  19.  *
  20.  * THIS PROGRAM HAS NO WARRANTY EXPRESSED OR IMPLIED. ANY DAMAGE CAUSED
  21.  * TO FILES OR COMPUTER SYSTEMS BY RUNNING THS PROGRAM IS NOT THE AUTHOR'S
  22.  * RESPONSIBILITY. USE THIS PROGRAM AT YOUR OWN RISK.
  23.  *
  24.  */
  25.  
  26. #include <exec/types.h>
  27. #include <exec/alerts.h>
  28. #include <exec/memory.h>
  29. #include <exec/libraries.h>
  30. #include <dos/dos.h>
  31. #include <dos/dosextens.h>
  32.  
  33. #define __USE_SYSBASE
  34. #include <proto/exec.h>
  35. #include <proto/utility.h>
  36. #include <proto/dos.h>
  37.  
  38. #include "debug.h"
  39.  
  40. static const TEXT verstag[] = "$VER: SecureDelete 42.1 (10.8.85)\0";
  41. static const TEXT ProgName[] = "SecureDelete";
  42. static const TEXT cmdtemplate[] = "FILE/A";
  43.  
  44. #define OS_LIB_VERSION 37L    /* release 2 or better */
  45. #define EMPTY_MEM_SIZE 512    /* kludgy - may look up device blocksize later */
  46.  
  47. long __builtin_getreg(int);
  48.  
  49. __regargs ULONG main (void)
  50. {
  51.     register struct ExecBase    *SysBase     = (*((struct ExecBase **)4L));
  52.     register struct DosLibrary    *DOSBase     = NULL;
  53.     register struct Library        *UtilityBase = NULL;
  54.     struct Process            *myProcess    = (struct Process *) FindTask(NULL);
  55.     struct FileInfoBlock    *fib        = NULL;
  56.     struct RDArgs            *rdargs        = NULL;
  57.     struct DevProc            *devproc    = NULL;
  58.     STRPTR        filename;
  59.     ULONG        rc = RETURN_FAIL;
  60.     ULONG        currblk;
  61.     ULONG        numblocks;
  62.     ULONG        remainder;
  63.     BPTR        fh = NULL;
  64.     BOOL        ovfail = TRUE;
  65.     void        *emptybuf = NULL;
  66.  
  67.     if (!( DOSBase = (struct DosLibrary *) OpenLibrary("dos.library", OS_LIB_VERSION )))
  68.     {
  69.         D(bug("%s: Couldn't open %s\n",ProgName,"dos.library"));
  70.         Alert( AG_OpenLib | AO_DOSLib );
  71.         myProcess->pr_Result2 = ERROR_INVALID_RESIDENT_LIBRARY;
  72.         goto cleanup;
  73.     }
  74.  
  75.     if (!( UtilityBase = OpenLibrary("utility.library", OS_LIB_VERSION )))
  76.     {
  77.         D(bug("%s: Couldn't open %s\n",ProgName,"utility.library"));
  78.         Alert( AG_OpenLib | AO_UtilityLib );
  79.         SetIoErr( ERROR_INVALID_RESIDENT_LIBRARY );
  80.         PrintFault( ERROR_INVALID_RESIDENT_LIBRARY, ProgName);
  81.         goto cleanup;
  82.     }
  83.  
  84.     if (!( rdargs = ReadArgs(cmdtemplate, (LONG *) &filename, NULL )))
  85.     {
  86.         D(bug("%s: Invalid command line arguments\n",ProgName));
  87.         PrintFault(IoErr(), ProgName);
  88.         goto cleanup;
  89.     }
  90.  
  91.     /* of course, what we are about to do is only valid under a filesystem */
  92.     /* you can do it on a handler but that makes no sense... */
  93.     if (!IsFileSystem(filename))
  94.     {
  95.         Printf("%s: Device of '%s' is not a FileSystem\n",ProgName);
  96.         rc = RETURN_ERROR; goto cleanup;
  97.     }
  98.  
  99.     if (!( fh = Open(filename, MODE_OLDFILE )))
  100.     {
  101.         D(bug("%s: Couldn't open file '%s'\n",ProgName,filename));
  102.         PrintFault(IoErr(), ProgName);
  103.         rc = RETURN_ERROR; goto cleanup;
  104.     }
  105.  
  106.     if (!( fib = (struct FileInfoBlock *) AllocDosObject(DOS_FIB, TAG_DONE )))
  107.     {
  108.         D(bug("%s: Couldn't allocate FileInfoBlock\n",ProgName));
  109.         PrintFault(IoErr(), ProgName);
  110.         goto cleanup;
  111.     }
  112.  
  113.     if (!(ExamineFH(fh,fib)))
  114.     {
  115.         D(bug("%s: Couldn't examine opened file '%s'\n",ProgName,filename));
  116.         PrintFault(IoErr(), ProgName);
  117.         goto cleanup;
  118.     }
  119.  
  120.     if (!( emptybuf = AllocMem(EMPTY_MEM_SIZE, MEMF_PUBLIC | MEMF_CLEAR )))
  121.     {
  122.         D(bug("%s: Couldn't allocate empty memory block\n",ProgName));
  123.         SetIoErr(ERROR_NO_FREE_STORE);
  124.         PrintFault(ERROR_NO_FREE_STORE, ProgName);
  125.         goto cleanup;
  126.     }
  127.  
  128.     /* use explicit long math calls to remain pure (compiler bug workaround) */
  129.  
  130.     numblocks = UDivMod32(fib->fib_Size,EMPTY_MEM_SIZE);
  131.     remainder = __builtin_getreg(1);
  132.  
  133.     /* overwrite each block */
  134.     if (numblocks)
  135.         for (currblk = 0; currblk < numblocks; currblk++)
  136.             if (Write(fh,emptybuf,EMPTY_MEM_SIZE) != EMPTY_MEM_SIZE)
  137.             {
  138.                 D(bug("%s: Error overwriting file '%s'\n",ProgName,filename));
  139.                 PrintFault(IoErr(), ProgName);
  140.                 rc = RETURN_ERROR; break;
  141.             }
  142.  
  143.     /* did we fail whilst in the loop? */
  144.     if (currblk == numblocks) ovfail = FALSE;
  145.  
  146.     /* overwrite remaining bytes */
  147.     if (remainder && !ovfail)
  148.         if (Write(fh,emptybuf,remainder) != remainder)
  149.         {
  150.             D(bug("%s: Error overwriting file '%s'\n",ProgName,filename));
  151.             PrintFault(IoErr(), ProgName);
  152.             rc = RETURN_ERROR;
  153.         }
  154.  
  155.     /* try and close the file */
  156.     if (!Close(fh))
  157.     {
  158.         D(bug("%s: Error closing file '%s'\n",ProgName,filename));
  159.         PrintFault(IoErr(), ProgName);
  160.         ovfail = TRUE; rc = RETURN_ERROR;
  161.     }
  162.     fh = NULL;
  163.  
  164.     /* only attempt to delete file if overwriting successful */
  165.     if (!ovfail)
  166.     {
  167.         if (!DeleteFile(filename))
  168.         {
  169.             /* DeleteFile() failed */
  170.             D(bug("%s: Error deleting file '%s'\n",ProgName,filename));
  171.             PrintFault(IoErr(), ProgName);
  172.             rc = RETURN_ERROR;
  173.         }
  174.         else
  175.         {
  176.             /* everything succeeded... */
  177.             Printf("%s: '%s' deleted securely\n",ProgName,filename);
  178.             rc = RETURN_OK; /* flag success */
  179.         }
  180.     }
  181.  
  182.     if (devproc = GetDeviceProc(filename,devproc))
  183.     {
  184.         /* always flush filesystem if we got this far */
  185.         if (!DoPkt(devproc->dvp_Port,ACTION_FLUSH,NULL,NULL,NULL,NULL,NULL))
  186.         {
  187.             D(bug("%s: Failed to flush filesystem\n",ProgName));
  188.             Printf("%s: Failed to flush filesystem\n",ProgName);
  189.             rc = RETURN_WARN; /* warn user that FLUSH failed */
  190.         }
  191.         FreeDeviceProc(devproc);
  192.     }
  193.     else
  194.     {
  195.         D(bug("%s: GetDeviceProc() failed on '%s'\n",ProgName,filename));
  196.         Printf("%s: Failed to flush filesystem\n",ProgName);
  197.         rc = RETURN_WARN; /* warn user that FLUSH failed */
  198.     }
  199.  
  200. cleanup:
  201.     if (emptybuf)        FreeMem(emptybuf,EMPTY_MEM_SIZE);
  202.     if (fib)            FreeDosObject(DOS_FIB,(APTR)fib);
  203.     if (fh)                Close(fh);
  204.     if (rdargs)            FreeArgs(rdargs);
  205.     if (UtilityBase)    CloseLibrary(UtilityBase);
  206.     if (DOSBase)        CloseLibrary((struct Library *)DOSBase);
  207.     return(rc);
  208. }
  209.